package com.exception;

import com.dto.BaseDto;
import com.dto.dataenum.MessageEnum;
import com.dto.dataenum.Messages;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.exceptions.jdbc4.CommunicationsException;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
//import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.RecoverableDataAccessException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Component
public class CustomExceptionResolver implements HandlerExceptionResolver {
    static Map<Class,String> exceptionMap = new HashMap<Class,String>();
    static{
    	exceptionMap.put(CustomException.class,"");
		exceptionMap.put(MyBatisSystemException.class,"数据库异常请联系管理员");
		exceptionMap.put(CannotGetJdbcConnectionException.class,"数据库异常请联系管理员");
		exceptionMap.put(MySQLIntegrityConstraintViolationException.class,"添加失败，已存在");
		exceptionMap.put(RecoverableDataAccessException.class,"数据库异常，请联系管理员");
		exceptionMap.put(CommunicationsException.class,"数据库异常，请联系管理员");
		exceptionMap.put(ConnectException.class,"数据库异常，请联系管理员");
		exceptionMap.put(UnauthorizedException.class,"权限不足");



	}
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object obj,
			Exception ex) {
		ex.printStackTrace();
		//System.out.println(ex.getClass().getName());
        ModelAndView mv = new ModelAndView();
		String backurl;
		// 判断ex异常类型是否为CustomException,如果是就将其赋给CustomException对象，如果不是new一个未知异常
		//ex.printStackTrace();
		CustomException ce = changeToCustomException(ex);
		String msg = ce.getMessage();
		// 将错误信息放入请求作用域中
		request.setAttribute("message", ce.getMessage());

		//msgs数组添加的 需要不跳转 的 直接返回消息异常处理
		try {
			MessageEnum[] msgs = {MessageEnum.SELECT_STUDENTSEARCH_FAIL,MessageEnum.SELECT_STUDENTCHANGECLAZZBYLOCKED_FAIL};
			int size = Arrays.asList(msgs).stream().filter(new MyPredicate(msg)).collect(Collectors.toList()).size();
			System.out.println(size + "  size---------------------");
			if(size>0){
				System.out.println("json---------------------");
				ObjectMapper objectMapper = new ObjectMapper();
				//异常处理后输出给前端依然是dto模式
				PrintWriter out = response.getWriter();
				out.print(objectMapper.writeValueAsString(new BaseDto(4001,msg)));
				out.flush();
				out.close();
			}else if(msg.equals(Messages.OPTION_FAIL)){
				PrintWriter out = response.getWriter();
				String js = "<script type='text/javascript'>alert('"+Messages.OPTION_FAIL+"');" +
				"location.href='/toLogin'" +
						"</script>";
				out.print(js);
				out.flush();
				out.close();
			}

			else {
				// 进行页面的跳转，跳转到错误信息页面
				System.out.println(request.getContextPath() + "----" + request.getRequestURI());
				backurl =  "page/arrive" + request.getRequestURI();
				request.setAttribute("msg", msg);
				System.out.println(msg + " " + ce.getMessage());
				request.setAttribute("backurl", backurl);
				request.getRequestDispatcher("/error/error.jsp").forward(request, response);
			}
		} catch (IOException | ServletException e) {
			//e.printStackTrace();
		}
		return mv;
	}
	//将系统异常转换为自定义异常
	public CustomException  changeToCustomException(Exception ex){
    	for(Map.Entry<Class,String> entry:exceptionMap.entrySet()){
			System.out.println(entry.getKey().getName() +  "   "+ ex.getClass().getName());
		}
    	String msg = exceptionMap.get(ex.getClass());//如果在map中找到了对应的异常类型，得到中文提示信息
		CustomException ce;
		if(ex instanceof CustomException){//instanceof 尝试转换 不成功也不会报错
			ce = (CustomException)ex;
			System.out.println("custom");
		}else {
			System.out.println(msg+"------------------------");
			msg = Optional.ofNullable(msg).orElse("未知异常");
			ce = new CustomException(msg);
		}
		return ce;
	}


	//自定义条件表达式 可以传参比较
	static class MyPredicate implements Predicate<MessageEnum> {
		String msg;
		public MyPredicate(String msg) {// 利用构造 传递自己相传的参数
			super();
			this.msg = msg;
		}
		@Override
		public boolean test(MessageEnum messageEnum) {// 集合循环产生 自动填入
			System.out.println(msg+ "  "+ messageEnum.getMsg());
			return msg.indexOf(messageEnum.getMsg()) >= 0 ? true : false;
		}

	}
}